package com.crane.framework.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crane.framework.constant.SystemConst;
import com.crane.framework.dto.MenuAddDTO;
import com.crane.framework.dto.MenuQueryDTO;
import com.crane.framework.dto.MenuUpdateDTO;
import com.crane.framework.dto.PermissionAssignmentDTO;
import com.crane.framework.dto.common.TreeNodeDTO;
import com.crane.framework.entity.Menu;
import com.crane.framework.entity.RoleMenu;
import com.crane.framework.exception.RRException;
import com.crane.framework.service.IMenuService;
import com.crane.framework.mapper.MenuMapper;
import com.crane.framework.service.IRoleMenuService;
import com.crane.framework.utils.CommonUtil;
import com.crane.framework.utils.SystemUtil;
import com.crane.framework.vo.MenuVO;
import com.crane.framework.vo.TotalBaseInfoVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 47349
 * @description 针对表【sys_menu(菜单表)】的数据库操作Service实现
 * @createDate 2024-01-18 03:25:36
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

  @Resource private IRoleMenuService roleMenuService;

  @Override
  public List<MenuVO> getMenuList(List<String> menuIdList, MenuQueryDTO queryDTO) {
    String title = null;
    String path = null;

    if (CommonUtil.notNullOrEmpty(queryDTO)) {
      title = queryDTO.getTitle();
      path = queryDTO.getPath();
    }

    List<Menu> menuList =
        this.lambdaQuery()
            .like(CommonUtil.notNullOrEmpty(title), Menu::getTitle, title)
            .like(CommonUtil.notNullOrEmpty(path), Menu::getPath, path)
            .in(CommonUtil.notNullOrEmpty(menuIdList), Menu::getId, menuIdList)
            .list();

    if (CommonUtil.isNullOrEmpty(menuList)) {
      return null;
    }

    Map<String, Menu> menuId2Item =
        menuList.stream().collect(Collectors.toMap(Menu::getId, Function.identity()));

    List<MenuVO> menuVOList = SystemUtil.buildResource(menuList, MenuVO.class);
    menuVOList.forEach(i -> i.setOrderNumber(menuId2Item.get((String) i.getId()).getOrderNumber()));

    return TreeNodeDTO.buildTreeFromFlatList(menuVOList, true);
  }

  @Override
  public void addMenu(MenuAddDTO addDTO) {
    Long count =
        this.lambdaQuery()
            .eq(Menu::getTitle, addDTO.getTitle())
            .or()
            .eq(Menu::getPath, addDTO.getPath())
            .count();

    if (count > 0) {
      throw new RuntimeException("该菜单已存在");
    }

    Menu menu = SystemUtil.buildResource(addDTO, Menu.class);
    this.save(menu);
  }

  @Override
  public void removeMenu(String id) {
    Menu menu = this.getById(id);

    if (CommonUtil.isNullOrEmpty(menu)) {
      throw new RRException("该菜单不存在");
    }

    String path = menu.getPath();

    if (SystemConst.CanNotDelMenuPaths.contains(path)) {
      throw new RRException("该菜单不能删除");
    }

    Long count = this.lambdaQuery().eq(Menu::getPid, id).count();

    if (count > 0) {
      throw new RRException("该菜单下存在子菜单");
    }

    this.removeById(id);
  }

  @Override
  public void updateMenu(MenuUpdateDTO updateDTO) {
    String id = updateDTO.getId();

    Menu menu = this.getById(id);

    if (CommonUtil.isNullOrEmpty(menu)) {
      throw new RRException("该菜单不存在");
    }

    String path = menu.getPath();

    if (SystemConst.CanNotDelMenuPaths.contains(path)) {
      throw new RRException("该菜单不能更改");
    }

    Menu menuUpdate = SystemUtil.buildResource(updateDTO, Menu.class);
    this.updateById(menuUpdate);
  }

  @Override
  public void permissionAssignment(PermissionAssignmentDTO permissionAssignmentDTO) {
    String roleId = permissionAssignmentDTO.getRoleId();
    List<String> menuIdList = permissionAssignmentDTO.getMenuIdList();

    List<RoleMenu> roleMenus = roleMenuService.lambdaQuery().eq(RoleMenu::getRoleId, roleId).list();
    if (CommonUtil.notNullOrEmpty(roleMenus)) {
      roleMenuService.removeByIds(roleMenus.stream().map(RoleMenu::getId).toList());
    }

    if (CommonUtil.isNullOrEmpty(menuIdList)) {
      return;
    }

    List<RoleMenu> list = new ArrayList<>();
    menuIdList.forEach(
        i -> {
          RoleMenu roleMenu = new RoleMenu();
          roleMenu.setRoleId(roleId);
          roleMenu.setMenuId(i);
          list.add(roleMenu);
        });

    roleMenuService.saveBatch(list);
  }

  @Override
  public List<String> getPermissionList(String roleId) {
    List<RoleMenu> roleMenuList =
        roleMenuService.lambdaQuery().eq(RoleMenu::getRoleId, roleId).list();
    if (CommonUtil.isNullOrEmpty(roleMenuList)) {
      return new ArrayList<>();
    }

    return roleMenuList.stream().map(RoleMenu::getMenuId).toList();
  }
}
